home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gxtype1.c < prev    next >
C/C++ Source or Header  |  1997-03-23  |  13KB  |  420 lines

  1. /* Copyright (C) 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gxtype1.c */
  20. /* Adobe Type 1 font interpreter support */
  21. #include "math_.h"
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gsccode.h"
  25. #include "gsline.h"
  26. #include "gsstruct.h"
  27. #include "gxarith.h"
  28. #include "gxfixed.h"
  29. #include "gxistate.h"
  30. #include "gxmatrix.h"
  31. #include "gxcoord.h"
  32. #include "gxfont.h"
  33. #include "gxfont1.h"
  34. #include "gxtype1.h"
  35. #include "gzpath.h"
  36.  
  37. /*
  38.  * The routines in this file are used for both Type 1 and Type 2
  39.  * charstring interpreters.
  40.  */
  41.  
  42. /*
  43.  * Define whether or not to force hints to "big pixel" boundaries
  44.  * when rasterizing at higher resolution.  With the current algorithms,
  45.  * a value of 1 is better for devices without alpha capability,
  46.  * but 0 is better if alpha is available.
  47.  */
  48. #define FORCE_HINTS_TO_BIG_PIXELS 1
  49.  
  50. /* Structure descriptor */
  51. public_st_gs_font_type1();
  52.  
  53. /* Encrypt a string. */
  54. int
  55. gs_type1_encrypt(byte *dest, const byte *src, uint len, crypt_state *pstate)
  56. {    register crypt_state state = *pstate;
  57.     register const byte *from = src;
  58.     register byte *to = dest;
  59.     register uint count = len;
  60.     while ( count )
  61.        {    encrypt_next(*from, state, *to);
  62.         from++, to++, count--;
  63.        }
  64.     *pstate = state;
  65.     return 0;
  66. }
  67. /* Decrypt a string. */
  68. int
  69. gs_type1_decrypt(byte *dest, const byte *src, uint len, crypt_state *pstate)
  70. {    register crypt_state state = *pstate;
  71.     register const byte *from = src;
  72.     register byte *to = dest;
  73.     register uint count = len;
  74.     while ( count )
  75.        {    /* If from == to, we can't use the obvious */
  76.         /*    decrypt_next(*from, state, *to);    */
  77.         register byte ch = *from++;
  78.         decrypt_next(ch, state, *to);
  79.         to++, count--;
  80.        }
  81.     *pstate = state;
  82.     return 0;
  83. }
  84.  
  85. /* Define the structure type for a Type 1 interpreter state. */
  86. public_st_gs_type1_state();
  87. /* GC procedures */
  88. #define pcis ((gs_type1_state *)vptr)
  89. private ENUM_PTRS_BEGIN(gs_type1_state_enum_ptrs) {
  90.     if ( index < pcis->ips_count + 3 )
  91.       {    ENUM_RETURN_CONST_STRING_PTR(gs_type1_state,
  92.                          ipstack[index - 3].char_string);
  93.       }
  94.     return 0;
  95.     }
  96.     ENUM_PTR(0, gs_type1_state, pfont);
  97.     ENUM_PTR(1, gs_type1_state, pis);
  98.     ENUM_PTR(2, gs_type1_state, path);
  99. ENUM_PTRS_END
  100. private RELOC_PTRS_BEGIN(gs_type1_state_reloc_ptrs) {
  101.     int i;
  102.     RELOC_PTR(gs_type1_state, pfont);
  103.     RELOC_PTR(gs_type1_state, pis);
  104.     RELOC_PTR(gs_type1_state, path);
  105.     for ( i = 0; i < pcis->ips_count; i++ )
  106.       {    ip_state *ipsp = &pcis->ipstack[i];
  107.         int diff = ipsp->ip - ipsp->char_string.data;
  108.         gs_reloc_const_string(&ipsp->char_string, gcst);
  109.         ipsp->ip = ipsp->char_string.data + diff;
  110.       }
  111. } RELOC_PTRS_END
  112. #undef pcis
  113.  
  114. /* ------ Interpreter entry point ------ */
  115.  
  116. private int
  117. gs_no_charstring_interpret(gs_type1_state *pcis, const gs_const_string *str,
  118.   int *pindex)
  119. {    return_error(gs_error_rangecheck);
  120. }
  121. int (*gs_charstring_interpreter[3])
  122.      (P3(gs_type1_state *pcis, const gs_const_string *str, int *pindex)) = {
  123.        gs_no_charstring_interpret,
  124.        gs_no_charstring_interpret,
  125.        gs_no_charstring_interpret
  126. };
  127.  
  128. /*
  129.  * Continue interpreting a Type 1 charstring.  If str != 0, it is taken as
  130.  * the byte string to interpret.  Return 0 on successful completion, <0 on
  131.  * error, or >0 when client intervention is required (or allowed).  The int*
  132.  * argument is where the othersubr # is stored for callothersubr.
  133.  */
  134. int
  135. gs_type1_interpret(gs_type1_state *pcis, const gs_const_string *str,
  136.   int *pindex)
  137. {    return (*gs_charstring_interpreter[pcis->pfont->data.CharstringType])
  138.       (pcis, str, pindex);
  139. }
  140.  
  141. /* ------ Interpreter services ------ */
  142.  
  143. #define s (*ps)
  144.  
  145. /* We export this for the Type 2 charstring interpreter. */
  146. void
  147. accum_xy_proc(register is_ptr ps, fixed dx, fixed dy)
  148. {    ptx += c_fixed(dx, xx),
  149.     pty += c_fixed(dy, yy);
  150.     if ( sfc.skewed )
  151.       ptx += c_fixed(dy, yx),
  152.       pty += c_fixed(dx, xy);
  153. }
  154.  
  155. /* Initialize a Type 1 interpreter. */
  156. /* The caller must supply a string to the first call of gs_type1_interpret. */
  157. int
  158. gs_type1_interp_init(register gs_type1_state *pcis, gs_imager_state *pis,
  159.   gx_path *ppath, const gs_log2_scale_point *pscale, bool charpath_flag,
  160.   int paint_type, gs_font_type1 *pfont)
  161. {    static const gs_log2_scale_point no_scale = { 0, 0 };
  162.     const gs_log2_scale_point *plog2_scale =
  163.       (FORCE_HINTS_TO_BIG_PIXELS ? pscale : &no_scale);
  164.  
  165.     pcis->pfont = pfont;
  166.     pcis->pis = pis;
  167.     pcis->path = ppath;
  168.     /*
  169.      * charpath_flag controls coordinate rounding, hinting, and
  170.      * flatness enhancement.  If we allow it to be set to true,
  171.      * charpath may produce results quite different from show.
  172.      */
  173.     pcis->charpath_flag = false /*charpath_flag*/;
  174.     pcis->paint_type = paint_type;
  175.     pcis->os_count = 0;
  176.     pcis->ips_count = 1;
  177.     pcis->ipstack[0].ip = 0;
  178.     pcis->ipstack[0].char_string.data = 0;
  179.     pcis->ipstack[0].char_string.size = 0;
  180.     pcis->ignore_pops = 0;
  181.     pcis->init_done = -1;
  182.     pcis->sb_set = false;
  183.     pcis->width_set = false;
  184.  
  185.     /* Set the sampling scale. */
  186.     set_pixel_scale(&pcis->scale.x, plog2_scale->x);
  187.     set_pixel_scale(&pcis->scale.y, plog2_scale->y);
  188.  
  189.     return 0;
  190. }
  191. /* Preset the left side bearing and/or width. */
  192. void
  193. gs_type1_set_lsb(gs_type1_state *pcis, const gs_point *psbpt)
  194. {    pcis->lsb.x = float2fixed(psbpt->x);
  195.     pcis->lsb.y = float2fixed(psbpt->y);
  196.     pcis->sb_set = true;
  197. }
  198. void
  199. gs_type1_set_width(gs_type1_state *pcis, const gs_point *pwpt)
  200. {    pcis->width.x = float2fixed(pwpt->x);
  201.     pcis->width.y = float2fixed(pwpt->y);
  202.     pcis->width_set = true;
  203. }
  204. /* Finish initializing the interpreter if we are actually rasterizing */
  205. /* the character, as opposed to just computing the side bearing and width. */
  206. void
  207. gs_type1_finish_init(gs_type1_state *pcis, gs_op1_state _ss *ps)
  208. {    gs_imager_state *pis = pcis->pis;
  209.  
  210.     /* Set up the fixed version of the transformation. */
  211.     gx_matrix_to_fixed_coeff(&ctm_only(pis), &pcis->fc, max_coeff_bits);
  212.     sfc = pcis->fc;
  213.  
  214.     /* Set the current point of the path to the origin, */
  215.     /* in anticipation of the initial [h]sbw. */
  216.     { gx_path *ppath = pcis->path;
  217.       ptx = pcis->origin.x = ppath->position.x;
  218.       pty = pcis->origin.y = ppath->position.y;
  219.     }
  220.  
  221.     /* Initialize hint-related scalars. */
  222.     pcis->have_hintmask = false;
  223.     pcis->seac_base = -1;
  224.     pcis->asb_diff = pcis->adxy.x = pcis->adxy.y = 0;
  225.     pcis->flex_count = flex_max;        /* not in Flex */
  226.     pcis->dotsection_flag = dotsection_out;
  227.     pcis->vstem3_set = false;
  228.     pcis->vs_offset.x = pcis->vs_offset.y = 0;
  229.     pcis->hints_initial = 0;        /* probably not needed */
  230.     pcis->hint_next = 0;
  231.     pcis->hints_pending = 0;
  232.  
  233.     /* Assimilate the hints proper. */
  234.     { gs_log2_scale_point log2_scale;
  235.       log2_scale.x = pcis->scale.x.log2_unit;
  236.       log2_scale.y = pcis->scale.y.log2_unit;
  237.       if ( pcis->charpath_flag )
  238.         reset_font_hints(&pcis->fh, &log2_scale);
  239.       else
  240.         compute_font_hints(&pcis->fh, &pis->ctm, &log2_scale,
  241.                    &pcis->pfont->data);
  242.     }
  243.     reset_stem_hints(pcis);
  244.  
  245.     /*
  246.      * Set the flatness to a value that is likely to produce reasonably
  247.      * good-looking curves, regardless of its current value in the
  248.      * graphics state.  If the character is very small, set the flatness
  249.      * to zero, which will produce very accurate curves.
  250.      */
  251.        {    float cxx = fabs(pis->ctm.xx), cyy = fabs(pis->ctm.yy);
  252.         if ( cyy < cxx )
  253.           cxx = cyy;
  254.         if ( !is_xxyy(&pis->ctm) )
  255.            {    float cxy = fabs(pis->ctm.xy), cyx = fabs(pis->ctm.yx);
  256.             if ( cxy < cxx )
  257.               cxx = cxy;
  258.             if ( cyx < cxx )
  259.               cxx = cyx;
  260.            }
  261.         /* Don't let the flatness be worse than the default. */
  262.         if ( cxx > pis->flatness )
  263.           cxx = pis->flatness;
  264.         /* If the character is tiny, force accurate curves. */
  265.         if ( cxx < 0.2 )
  266.           cxx = 0;
  267.         pcis->flatness = cxx;
  268.        }
  269.  
  270.     /* Move to the side bearing point. */
  271.     accum_xy(pcis->lsb.x, pcis->lsb.y);
  272.     pcis->position.x = ptx;
  273.     pcis->position.y = pty;
  274.  
  275.     pcis->init_done = 1;
  276. }
  277.  
  278. /* ------ Operator procedures ------ */
  279.  
  280. /* We put these before the interpreter to save having to write */
  281. /* prototypes for all of them. */
  282.  
  283. int
  284. gs_op1_closepath(register is_ptr ps)
  285. {    /* Note that this does NOT reset the current point! */
  286.     gx_path *ppath = sppath;
  287.     subpath *psub;
  288.     segment *pseg;
  289.     fixed dx, dy;
  290.     int code;
  291.  
  292.     /* Check for and suppress a microscopic closing line. */
  293.     if ( (psub = ppath->current_subpath) != 0 &&
  294.          (pseg = psub->last) != 0 &&
  295.          (dx = pseg->pt.x - psub->pt.x,
  296.           any_abs(dx) < float2fixed(0.1)) &&
  297.          (dy = pseg->pt.y - psub->pt.y,
  298.           any_abs(dy) < float2fixed(0.1))
  299.        )
  300.       switch ( pseg->type )
  301.         {
  302.         case s_line:
  303.           code = gx_path_pop_close_subpath(sppath);
  304.           break;
  305.         case s_curve:
  306.           /*
  307.            * Unfortunately, there is no "s_curve_close".  (Maybe there
  308.            * should be?)  Just adjust the final point of the curve so it
  309.            * is identical to the closing point.
  310.            */
  311.           pseg->pt = psub->pt;
  312. #define pcseg ((curve_segment *)pseg)
  313.           pcseg->p2.x -= dx;
  314.           pcseg->p2.y -= dy;
  315. #undef pcseg
  316.           /* falls through */
  317.         default:
  318.           /* What else could it be?? */
  319.           code = gx_path_close_subpath(sppath);
  320.         }
  321.     else
  322.       code = gx_path_close_subpath(sppath);
  323.     if ( code < 0 )
  324.       return code;
  325.     return gx_path_add_point(ppath, ptx, pty);    /* put the point where it was */
  326. }
  327.  
  328. int
  329. gs_op1_rrcurveto(register is_ptr ps, fixed dx1, fixed dy1,
  330.   fixed dx2, fixed dy2, fixed dx3, fixed dy3)
  331. {    gs_fixed_point pt1, pt2;
  332.     fixed ax0 = sppath->position.x - ptx;
  333.     fixed ay0 = sppath->position.y - pty;
  334.     accum_xy(dx1, dy1);
  335.     pt1.x = ptx + ax0, pt1.y = pty + ay0;
  336.     accum_xy(dx2, dy2);
  337.     pt2.x = ptx, pt2.y = pty;
  338.     accum_xy(dx3, dy3);
  339.     return gx_path_add_curve(sppath, pt1.x, pt1.y, pt2.x, pt2.y, ptx, pty);
  340. }
  341.  
  342. #undef s
  343.  
  344. /* Record the side bearing and character width. */
  345. int
  346. gs_type1_sbw(gs_type1_state *pcis, fixed lsbx, fixed lsby, fixed wx, fixed wy)
  347. {    if ( !pcis->sb_set )
  348.       pcis->lsb.x = lsbx, pcis->lsb.y = lsby,
  349.         pcis->sb_set = true;    /* needed for accented chars */
  350.     if ( !pcis->width_set )
  351.       pcis->width.x = wx, pcis->width.y = wy,
  352.         pcis->width_set = true;
  353.     if_debug4('1',"[1]sb=(%g,%g) w=(%g,%g)\n",
  354.           fixed2float(pcis->lsb.x), fixed2float(pcis->lsb.y),
  355.           fixed2float(pcis->width.x), fixed2float(pcis->width.y));
  356.     return 0;
  357. }
  358.  
  359. /* Handle the end of a character. */
  360. int
  361. gs_type1_endchar(gs_type1_state *pcis)
  362. {    gs_imager_state *pis = pcis->pis;
  363.     gx_path *ppath = pcis->path;
  364.  
  365.     if ( pcis->hint_next != 0 || path_is_drawing(ppath) )
  366.       apply_path_hints(pcis, true);
  367.     /* Set the current point to the character origin */
  368.     /* plus the width. */
  369.     { gs_fixed_point pt;
  370.  
  371.       gs_point_transform2fixed(&pis->ctm,
  372.                    fixed2float(pcis->width.x),
  373.                    fixed2float(pcis->width.y),
  374.                    &pt);
  375.       gx_path_add_point(ppath, pt.x, pt.y);
  376.     }
  377.     if ( pcis->scale.x.log2_unit + pcis->scale.y.log2_unit == 0 )
  378.     {    /*
  379.          * Tweak up the fill adjustment.  This is a hack for when
  380.          * we can't oversample.  The values here are based entirely
  381.          * on experience, not theory, and are designed primarily
  382.          * for displays and low-resolution fax.
  383.          */
  384.         gs_fixed_rect bbox;
  385.         int dx, dy, dmax;
  386.  
  387.         gx_path_bbox(ppath, &bbox);
  388.         dx = fixed2int_ceiling(bbox.q.x - bbox.p.x);
  389.         dy = fixed2int_ceiling(bbox.q.y - bbox.p.y);
  390.         dmax = max(dx, dy);
  391.         if ( pcis->fh.snap_h.count || pcis->fh.snap_v.count ||
  392.              pcis->fh.a_zone_count
  393.            )
  394.         {    /* We have hints.  Only tweak up a little at */
  395.             /* very small sizes, to help nearly-vertical */
  396.             /* or nearly-horizontal diagonals. */
  397.             pis->fill_adjust.x = pis->fill_adjust.y =
  398.                 (dmax < 15 ? float2fixed(0.15) :
  399.                  dmax < 25 ? float2fixed(0.1) :
  400.                  fixed_0);
  401.         }
  402.         else
  403.         {    /* No hints.  Tweak a little more to compensate */
  404.             /* for lack of snapping to pixel grid. */
  405.             pis->fill_adjust.x = pis->fill_adjust.y =
  406.                 (dmax < 10 ? float2fixed(0.2) :
  407.                  dmax < 25 ? float2fixed(0.1) :
  408.                  float2fixed(0.05));
  409.         }
  410.     }
  411.     else
  412.     {    /* Don't do any adjusting. */
  413.         pis->fill_adjust.x = pis->fill_adjust.y = fixed_0;
  414.     }
  415.     /* Set the flatness for curve rendering. */
  416.     if ( !pcis->charpath_flag )
  417.       gs_imager_setflat(pis, pcis->flatness);
  418.     return 0;
  419. }
  420.